#include <iostream>
#include <iterator>
#include <vector>
#include <string>


// Spirit のコードをインクルード (必要なものだけ)
#include <boost/spirit/iterator/file_iterator.hpp>
#include <boost/spirit/core.hpp>

#ifndef _CSV_PARSER
#define _CSV_PARSER


using namespace std;
using namespace boost::spirit;

template<typename IteratorT> struct push_pos {
   vector<IteratorT>& iter;

   push_pos(vector<IteratorT>& it): iter(it) { }

   void operator()( IteratorT first, IteratorT last ) const 
   {
    if(first.make_end() != last) // take off eof
      iter.push_back(last);
    }

};


// 値をベクタにコピーする Semantic Action
// // 組み込みの append と同じような処理をしている(と思う)が、ここでは、
// // ダブルクォートが重なっていたら、1つに落とすという処理が追加されている
struct push_val {
    vector<string>& values;
    push_val( vector<string>& vec ) : values(vec) { }

    template<class IteratorT>
    void operator()(IteratorT first, IteratorT last) const { // const が重要 
#ifdef _MSC_VER
        // なぜか VC6 だとコンストラクタによる初期化がうまくいかない
        string s;
        s.resize(distance(first, last));
        for (size_t i = 0; first != last; ++i) {
            s[i] = *first++;
        }
#else
        string s( first, last );
#endif
        string::size_type pos = 0;
        while (1) {
            pos = s.find("\"\"", pos);
            if (pos == string::npos)
                break;
            ++pos;
            s.erase(pos, 1);
        }
        values.push_back(s);
    }
};


// csv パーザ
template<typename IteratorT> struct csv_parser : public grammar<csv_parser<IteratorT> > {
    vector<string>& v;
    vector<IteratorT>& pos; 

    csv_parser<IteratorT> ( vector<string>& vec, vector<IteratorT>& it ) : v(vec), pos(it) { }

    template<typename ScannerT> struct definition {
        rule<ScannerT> csv, val, quoted_val, naked_val;

        definition(const csv_parser<IteratorT>& self)
        {
            csv = val >> *(',' >> val) >> (end_p | eol_p[push_pos<IteratorT>(self.pos)] );

            val = *blank_p >>
                  ch_p('\"') >> quoted_val[push_val(self.v)] >> ch_p('\"') >>
                  *blank_p
                | naked_val[push_val(self.v)];

            quoted_val = *(~ch_p('"') | str_p("\"\""));

            naked_val = *(~ch_p(',') & ~ch_p('\"') & ~ch_p('\n'));
        }

        const rule<ScannerT>& start() const { return csv; }
    };
};


template<typename IteratorT> class csv_parser_info
{

public:

  // パーザ呼び出し用のラッパ関数
  //static parse_info<IteratorT> parse_csv(const IteratorT& first, const IteratorT& last, vector<string>& v, vector<IteratorT>& i)
  parse_info<IteratorT> parse_csv(const IteratorT& first, const IteratorT& last, vector<string>& v, vector<IteratorT>& i)
  {
     csv_parser<IteratorT> csv(v, i);

     return parse(first, last, csv);
  }

  parse_info<IteratorT> parse_csv(const IteratorT& first, const IteratorT& last)
  {
	init();
    return parse_csv(first, last, _line, _iter);
  }


  csv_parser_info<IteratorT>(char const* filename): _line() 
  { 
    IteratorT i(filename);

    if(i) { _iter.push_back(i); } 
  }

  csv_parser_info<IteratorT>(IteratorT const& i): _line() { 
    if(i) { _iter.push_back(i); } 
  }

  vector<string> const& line() const { 
  
	return _line; 
   }

  ~csv_parser_info()
   {
	this->init();
   }

private:
  
    void init() { _line.clear(); _iter.clear(); }

    vector<IteratorT> _iter;
    vector<string> _line;

    // Spirit は forwardイテレータを要求するので、ifstream では力不足。
    //     // そのため spirit が用意している file_iterator を使う。
    //typedef IteratorT iterator_t;

    // ファイルを開いて、その先頭を指すイテレータを生成
};



#endif
